package com.sfx.concurrent.demo.concurrent.Lock;

import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.AbstractQueuedSynchronizer;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;

/**
 * Created with IntelliJ IDEA.
 * Description:
 * User: sfx
 * Date: 2023-01-29
 * Time: 16:29
 */
class MyLock implements Lock {
    //同步器类  -->独占锁
    class Sync extends AbstractQueuedSynchronizer {
        @Override  //尝试获取锁
        protected boolean tryAcquire(int arg) {
            //尝试设置状态: 0->1 ,compareAndSetState 来保证线程安全
            if (compareAndSetState(0,1)) {
                //获取到锁,将owner(持有锁线程)线程设置为当前线程
                setExclusiveOwnerThread(Thread.currentThread());
                //尝试获取锁成功
                return true;
            }
            //尝试加锁失败
            return false;
        }

        @Override   //尝试释放锁
        protected boolean tryRelease(int arg) {
            //释放锁,将持有锁线程设置为null
            setExclusiveOwnerThread(null);
            //将状态改为0,因为这个是volatile的,能够保证前面的代码不跑到后面去,保证指令重排序
            setState(0);
            return true;
        }

        @Override  //是否持有独占锁
        protected boolean isHeldExclusively() {
            //状态为1代表持有独占锁
            return getState() == 1;
        }
        //获取条件变量
        public Condition newCondition() {
            return new ConditionObject();
        }
    }

    //同步器对象
    private Sync sync = new Sync();
    @Override  //加锁  不成功进入等待队列等待
    public void lock() {
        sync.acquire(1);
    }

    @Override  //可打断的加锁
    public void lockInterruptibly() throws InterruptedException {
        sync.acquireInterruptibly(1);
    }

    @Override  //尝试加锁  只会尝试一次
    public boolean tryLock() {
        return sync.tryAcquire(1);
    }

    @Override  //尝试加锁 只会尝试一次 有时限的
    public boolean tryLock(long time, TimeUnit unit) throws InterruptedException {
        return sync.tryAcquireNanos(1, unit.toNanos(time));
    }

    @Override  //解锁
    public void unlock() {
        sync.release(1);
    }

    @Override  //创建条件变量
    public Condition newCondition() {
        return sync.newCondition();
    }
}
//不可重入锁
@Slf4j(topic = "c.TestAQS")
public class TestAQS {
    public static void main1(String[] args) {
        MyLock lock = new MyLock();
        new Thread(()->{
            lock.lock();
            try{
                log.debug("locking...");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }finally {
                log.debug("unlocking...");
                lock.unlock();
            }
        },"t1").start();
        new Thread(()->{
            lock.lock();
            try{
                log.debug("locking...");
            }finally {
                log.debug("unlocking...");
                lock.unlock();
            }
        },"t2").start();
    }
    public static void main(String[] args) {
        MyLock lock = new MyLock();
        new Thread(()->{
            lock.lock();
            log.debug("locking...");
            lock.lock();
            log.debug("locking...");
        },"t1").start();
    }
}